using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Status;
using System.Net.Sockets;
using System.Net;
using System.Diagnostics;
using System.IO;
namespace SmsServerClient
{
    public partial class ConnectForm : Form
    {
        Microsoft.WindowsMobile.Status.SystemState ActivesyncConnection;
        TcpSocketClass MySocket;
        SmsListener SmsFilter;
        IntPtr hLibModule;
        delegate void ConnectionStatusUpdateDelegate(string Message);
        delegate void StatUpdateDelegate();
        delegate void InfoBoxUpdateDelegate(string Message);
        int cMessageReceived = 0;
        int cMessageSent = 0;
        int cMessageSentFailed = 0;
        public static void WriteLogDB(string str)
        {
            try
            {
                TextWriter writer = new StreamWriter("\\My Documents\\SMSSentLog.txt", true);
                writer.WriteLine(str);
                writer.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error Writing the logfile", ex.Message);
            }
        }

        public ConnectForm()
        {
            InitializeComponent();
            ConnectionStatusUpdate("Initializing..");
            StatUpdate();
            do
            {
                ConnectionStatusUpdate("Trying Port:" + Settings.TcpPort.ToString());
                Application.DoEvents();
                MySocket = new TcpSocketClass(Settings.TcpPort);
                if (MySocket.PortInUse == -1)
                {
                    Settings.TcpPort = (Int16)(new Random()).Next(10000, 32000);
                    Settings.Update();
                }
            } while (MySocket.PortInUse == -1);
            MySocket.MessageReceived += new TcpSocketClass.MessageReceivedDelegate(MySocket_MessageReceived);
            MySocket.Connected += new TcpSocketClass.ConnectedDelegate(MySocket_Connected);
            MySocket.Disconnected += new TcpSocketClass.DisconnectedDelegate(MySocket_Disconnected);
            MySocket.CommandReceived += new TcpSocketClass.CommandReceivedDelegate(MySocket_CommandReceived);
            MySocket.SmsReceived += new TcpSocketClass.SmsReceivedDelegate(MySocket_SmsReceived);
            SmsFilter = new SmsListener();
            hLibModule = UnmanagedAPI.LoadLibrary("mapirule.dll");
            //UnmanagedAPI.DllRegisterServer();
            UnmanagedAPI.ChangeCapturingFlag(false);
            SmsFilter.FilterSmsReceived += new SmsListener.FilterSmsReceivedDelegate(SmsFilter_FilterSmsReceived);
            ActivesyncConnection = new SystemState(SystemProperty.CradlePresent);
            ActivesyncConnection.Changed += new ChangeEventHandler(ActivesyncConnection_Changed);
            ActivesyncConnection_Changed(null, null);
        }

        void MySocket_SmsReceived(SmsClass Message)
        {
            int i=0;
            bool sent = false;
            //WriteLogDB(Message.ToString());
            while (sent == false && i < 3)
            {
                sent = SmsSender.SendSms(Message.Number, Message.Body) == 0 ? true : false;
                i++;
                //try
                //{
                //    SmsMessage SendMessage = new SmsMessage(Message.Number, Message.Body);
                //    SendMessage.Send();
                //    sent = true;
                //}
                //catch(Exception ex)
                //{
                //    InfoBoxUpdate("Sent Failed:" + ex.Message);
                //    i++;
                //}
                //MySocket_MessageReceived(sent.ToString());
            }
            DeliveryReportClass DeliveryReport = new DeliveryReportClass();
            DeliveryReport.MessageID = Message.MessageID;
            if (sent == true)
            {
                DeliveryReport.Status = DeliveryStatusEnum.Sent;
                cMessageSent++;
            }
            else
            {
                DeliveryReport.Status = DeliveryStatusEnum.Failed;
                cMessageSentFailed++;
            }
            StatUpdate();
            MySocket.SendMessage(DeliveryReport.ToString());
        }

        void MySocket_CommandReceived(CommandClass Command)
        {
            if (Command.Type == CommandTypeEnum.GetInboxMessage)
            {
                IntPtr pMAPI = UnmanagedAPI.MapiLogin("Sms");
                int i = 0;
                try
                {
                    StringBuilder Message = new StringBuilder(1464);
                    StringBuilder Number = new StringBuilder(64);
                    FILETIME ft = new FILETIME();
                    FILETIME lft = new FILETIME();
                    DateTime lftDate = new DateTime(Convert.ToInt64(Command.Value));
                    lft.FromDateTime(lftDate);
                    bool ShouldDelete = Settings.DeleteInbox == "true";
                    while (UnmanagedAPI.GetNextMessage(pMAPI, lft, Message, Number, ref ft, ShouldDelete) && MySocket.IsConnected == 1)
                    {
                        string CleanedNumber = HelperClass.CleanNumber(Number.ToString());
                        if (Settings.BlockNonNumberic == "true" && CleanedNumber == string.Empty)
                            continue;
                        else
                            CleanedNumber = Number.ToString();
                        i++;
                        SmsClass InboxSms = new SmsClass();
                        InboxSms.Body = Message.ToString();
                        InboxSms.Number = CleanedNumber;
                        InboxSms.Time = HelperClass.FileTime2DateTime(ft);
                        MySocket.SendMessage(InboxSms.ToString());
                        cMessageReceived++;
                        StatUpdate();
                    }
                    InfoBoxUpdate("Finished reading Inbox");
                }
                catch(Exception ex)
                {
                    InfoBoxUpdate("GetInboxMessage Failed:" + ex.Message);
                }
                finally
                {
                    if (pMAPI != IntPtr.Zero)
                        UnmanagedAPI.MapiLogout(pMAPI);
                }
            }
            else if (Command.Type == CommandTypeEnum.StartFilter)
            {
                if (MySocket != null && MySocket.IsConnected == 1)
                {
                    SmsFilter.InitThread();
                    bool Response = UnmanagedAPI.ChangeCapturingFlag(true);
                    InfoBoxUpdate("Capture Started:" + Response.ToString());
                }
                else
                    MessageBox.Show("something wrong");
            }
            else if (Command.Type == CommandTypeEnum.StopFilter)
            {
                bool Response = UnmanagedAPI.ChangeCapturingFlag(false);
                InfoBoxUpdate("Capture Stopped:" + Response.ToString());
            }
            else if (Command.Type == CommandTypeEnum.CloseApplication)
            {
                InfoBoxUpdate("Closing Application");
                ExitMenuItem_Click(null, null);
            }
            else if (Command.Type == CommandTypeEnum.SetValue)
            {
                switch (Command.Name)
                {
                    case "DeleteInbox":
                        Settings.DeleteInbox = Command.Value;
                        break;
                    case "AdminNumber":
                        Settings.AdminNumber = Command.Value;
                        break;
                    case "InformAdmin":
                        Settings.InformAdmin = Command.Value;
                        break;
                    case "BlockNonNumberic":
                        Settings.BlockNonNumberic = Command.Value;
                        break;
                    case "InformClient":
                        Settings.InformClient = Command.Value;
                        break;
                }
                Settings.Update();
            }
        }

        void SmsFilter_FilterSmsReceived(SmsClass Message)
        {
            if (MySocket != null && MySocket.IsConnected == 1)
                MySocket.SendMessage(Message.ToString());
            else
            {
                InfoBoxUpdate("Error: Socket Closed, Filter Active");
            }
            cMessageReceived++;
            StatUpdate();
        }

        void MySocket_Disconnected(bool ShouldRestart)
        {
            if (Settings.InformAdmin == "true")
            {
                bool sent = false;
                int i = 0;
                while (sent == false && i < 3)
                {
                    sent = SmsSender.SendSms(Settings.AdminNumber, "Info: The Sms Server is down") == 0 ? true : false;
                    i++;
                    //try
                    //{
                    //    SmsMessage SendMessage = new SmsMessage(Settings.AdminNumber, "Info: The Sms Server is down");
                    //    SendMessage.Send();
                    //    sent = true;
                    //}
                    //catch (Exception ex)
                    //{
                    //    InfoBoxUpdate("Admin Sent Failed:" + ex.Message);
                    //    i++;
                    //}
                }
            }
            ConnectionStatusUpdate("Disconnected TCP");
            bool Response = UnmanagedAPI.ChangeCapturingFlag(false);
            InfoBoxUpdate("Capture Stopped:" + Response.ToString());
            SmsFilter.EndThread();
            ConnectionStatusUpdate("Reader Thread Ended");
            if (ShouldRestart == true)
            {
                ActivesyncConnection_Changed(null, null);
            }
        }

        void MySocket_Connected()
        {
            ConnectionStatusUpdate("Connected via TCP");
        }

        void ConnectionStatusUpdate(string Message)
        {
            if (InvokeRequired)
            {
                Invoke(new ConnectionStatusUpdateDelegate(ConnectionStatusUpdate), new object[] { Message });
            }
            else
            {
                ConnectionStatusTextBox.Text = Message;
            }
        }

        void StatUpdate()
        {
            if (InvokeRequired)
            {
                Invoke(new StatUpdateDelegate(StatUpdate), new object[] {});
            }
            else
            {
                StatTextBox.Text = string.Format("Sent:{0} Recd:{1} Fail:{2}", cMessageSent, cMessageReceived,cMessageSentFailed);
            }
        }

        void MySocket_MessageReceived(string Message)
        {
            InfoBoxUpdate(Message);
        }

        void InfoBoxUpdate(string Message)
        {
            if (InvokeRequired)
            {
                Invoke(new InfoBoxUpdateDelegate(InfoBoxUpdate), new object[] { Message });
            }
            else
            {
                if (InfoTextBox.Text.Length > 1024)
                    InfoTextBox.Text = string.Format("{0}\r\n", Message);
                else
                    InfoTextBox.Text += string.Format("{0}\r\n", Message);
            }
        }

        void ActivesyncConnection_Changed(object sender, ChangeEventArgs args)
        {
            if (SystemState.CradlePresent)
            {
                bool success = MySocket.StartListener();
                if(success == true)
                    ConnectionStatusUpdate("Listening port:" + MySocket.PortInUse.ToString());
                else
                    ConnectionStatusUpdate("Error Code:001"); // Error Code : 001 -> Unable to start Listener
            }
            else
            {
                if (MySocket.IsConnected == 1)
                    MySocket.Disconnect(false);
                ConnectionStatusUpdate("Cradle Removed");
            }
        }

        
        private void ExitMenuItem_Click(object sender, EventArgs e)
        {
            ConnectionStatusUpdate("Disconnect Socket");
            if (MySocket != null && MySocket.IsConnected == 1)
            {
                MySocket.Disconnect(false);
                MySocket = null;

            }
            ConnectionStatusUpdate("Free Library");            
            if (hLibModule != IntPtr.Zero)
                UnmanagedAPI.FreeLibrary(hLibModule);
            ConnectionStatusUpdate("Exiting Code..");
            Application.Exit();
        }

    }
}